package com.itheima.appserver.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.itheima.appserver.exception.MyException;
import com.itheima.appserver.exception.ResultError;
import com.itheima.appserver.interceptor.UserThreadLocal;
import com.itheima.appserver.service.CommentService;
import com.itheima.appserver.service.VideoService;
import com.itheima.commons.constants.Constants;
import com.itheima.commons.pojo.*;
import com.itheima.commons.vo.CommentVo;
import com.itheima.commons.vo.PageResult;
import com.itheima.commons.vo.VideoVo;
import com.itheima.interfaces.CommentApi;
import com.itheima.interfaces.UserInfoApi;
import com.itheima.interfaces.VideosApi;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class VideoServiceImpl implements VideoService {

    @Autowired
    protected FastFileStorageClient storageClient;

    @Autowired
    private FdfsWebServer fdfsWebServer;

    @Reference
    private VideosApi videosAPI;

    @Autowired
    private PidService pidService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Reference
    private UserInfoApi userInfoAPI;

    @Autowired
    private CommentService commentService;

    @Reference
    private CommentApi commentAPI;

    @Override
    public void loadVideo(MultipartFile videoThumbnail, MultipartFile videoFile) {
        if (ObjectUtil.isEmpty(videoFile)) {
            throw new MyException(ResultError.videoIsNullError());
        }
        String subAfter = StrUtil.subAfter(videoThumbnail.getOriginalFilename(), ".", true);
        if (!StrUtil.equalsAny(subAfter, "jpg", "png", "jpeg")) {
            throw new MyException(ResultError.fileFormatError());
        }
        String subVideo = StrUtil.subAfter(videoFile.getOriginalFilename(), ".", true);
        if (!StrUtil.equalsAny(subVideo, "avi", "mov", "mp4", "rm", "rmvb")) {
            throw new MyException(ResultError.videoFormatError());
        }

        if (videoFile.getSize() / 1024 / 1024 >= 40) {
            throw new MyException(ResultError.videoFormatError());
        }

        try {
            StorePath picPath = storageClient.uploadFile(videoThumbnail.getInputStream(), videoThumbnail.getSize(), StrUtil.subAfter(videoThumbnail.getOriginalFilename(), ".", true), null);
            StorePath videoPath = storageClient.uploadFile(videoFile.getInputStream(), videoFile.getSize(), StrUtil.subAfter(videoThumbnail.getOriginalFilename(), ".", true), null);
            Video video = new Video();
            video.setId(new ObjectId());
            Long vids = pidService.pidPro("VIDEOS");
            video.setVid(vids);
            video.setUserId(UserThreadLocal.getUserId());
            video.setText("天气真好啊");
            video.setPicUrl(fdfsWebServer.getWebServerUrl() + picPath.getFullPath());
            video.setVideoUrl(fdfsWebServer.getWebServerUrl() + videoPath.getFullPath());
            video.setCreated(System.currentTimeMillis());
            video.setSeeType(null);
            video.setSeeList(null);
            video.setNotSeeList(null);
            video.setLongitude("116.3504260");
            video.setLatitude("40.066350");
            video.setLocationName("浙江杭州");

            videosAPI.saveVideo(video);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public PageResult videoList(Integer page, Integer pagesize) {
        //从redis中查找自己推荐的vid视频
        String vids = redisTemplate.opsForValue().get(Constants.VIDEOS_RECOMMEND + UserThreadLocal.getUserId());
        List<Video> videoList = new ArrayList<>();
        if (StrUtil.isEmpty(vids)) {
            //随机生成vid
            videoList = videosAPI.randomByVid(pagesize);
        } else {
            List<String> vidList = StrUtil.split(vids, ",");
            //根据vid查找推荐视频
            page = (page - 1) * pagesize;
            //手动分页
            List<String> stringList = CollUtil.sub(vidList, page, Math.min(page + pagesize, vidList.size()));

            videoList = videosAPI.selectByVid(Convert.toLongArray(stringList));
        }

        List<VideoVo> list = new ArrayList<>();
        for (Video vv : videoList) {
            VideoVo videoVo = new VideoVo();
            videoVo.setId(vv.getId().toHexString());
            videoVo.setUserId(vv.getUserId());
            //根据userId查找userinfo表中用户信息
            UserInfo userInfo = userInfoAPI.findUserInfoByUserId(vv.getUserId());
            videoVo.setAvatar(userInfo.getLogo());
            videoVo.setNickname(userInfo.getNickName());
            videoVo.setCover(vv.getPicUrl());
            videoVo.setVideoUrl(vv.getVideoUrl());
            videoVo.setSignature("不签");
            Long likeCount = Convert.toLong(redisTemplate.opsForHash().get(Constants.VIDEOS_INTERACT_KEY + vv.getId(), Constants.VIDEO_LIKE_HASHKEY));
            if (ObjectUtil.isEmpty(likeCount)) {
                //去mongodb中找
                likeCount = commentAPI.selectLikeSize(vv.getId().toHexString());
                //存入redis中
                redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + vv.getId(), Constants.VIDEO_LIKE_HASHKEY, likeCount.toString());
            }
            videoVo.setLikeCount(Convert.toInt(likeCount));

            Boolean hasKey = redisTemplate.opsForHash().hasKey(Constants.VIDEOS_INTERACT_KEY + vv.getId(), Constants.VIDEO_ISLIKE_HASHKEY + UserThreadLocal.getUserId());
            if (!hasKey) {
                //去mongodb中查找
                hasKey = commentAPI.selectIsLike(vv.getId().toHexString(), UserThreadLocal.getUserId());
                if (hasKey) {
                    //存入redis中
                    redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + vv.getId(), Constants.VIDEO_ISLIKE_HASHKEY + UserThreadLocal.getUserId(), "1");
                }
            }
            videoVo.setHasLiked(hasKey ? 1 : 0);

            Boolean followKey = redisTemplate.opsForHash().hasKey(Constants.VIDEOS_INTERACT_KEY + vv.getUserId(), Constants.VIDEO_FOLLOW_HASHKEY + UserThreadLocal.getUserId());
            if (!followKey) {
                //去mongodb中查找
               followKey = commentAPI.selectIsFollow(vv.getUserId(),UserThreadLocal.getUserId());
                if (followKey) {
                    //存入redis中
                    redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + vv.getId(), Constants.VIDEO_FOLLOW_HASHKEY + UserThreadLocal.getUserId(), "1");
                }
            }
            videoVo.setHasFocus(followKey ? 1 : 0);
            Long commentCount = Convert.toLong(redisTemplate.opsForHash().get(Constants.VIDEOS_INTERACT_KEY + vv.getId(), Constants.VIDEO_COMMENT_HASHKEY));
            if (ObjectUtil.isEmpty(commentCount)) {
                //去mongodb中找
                commentCount = commentAPI.selectCommentSize(vv.getId().toHexString());
                //存入redis中
                redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + vv.getId(), Constants.VIDEO_LIKE_HASHKEY, commentCount.toString());
            }
            videoVo.setCommentCount(Convert.toInt(commentCount));
            list.add(videoVo);
        }

        return new PageResult(page, pagesize, 0L, list);
    }

    @Override
    public void videoLike(String id) {
        Long likeVideo = commentService.likeComment(id);

        //存入数量存入到redis中
        redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + id, Constants.VIDEO_LIKE_HASHKEY, likeVideo.toString());
        //把是否点赞存入redis
        redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + id, Constants.VIDEO_ISLIKE_HASHKEY + UserThreadLocal.getUserId(), "1");

    }

    @Override
    public void videoDisLike(String id) {
        Long disLikeVideo = videosAPI.disLikeVideo(id, UserThreadLocal.getUserId());

        //存入数量存入到redis中
        redisTemplate.opsForHash().put(Constants.MOVEMENTS_INTERACT_KEY + id, Constants.VIDEO_LIKE_HASHKEY, disLikeVideo.toString());
        //删除点赞
        redisTemplate.opsForHash().delete(Constants.MOVEMENTS_INTERACT_KEY + id, Constants.VIDEO_ISLIKE_HASHKEY + UserThreadLocal.getUserId());
    }

    @Override
    public PageResult queryCommentsList(String movementId, Integer page, Integer pagesize) {
        List<Comment> commentList = commentAPI.selectByPublishId(movementId, page, pagesize);
        if (CollUtil.isEmpty(commentList)) {
            return new PageResult();
        }
        //拿取评论人的id
        List<Long> userId = CollUtil.getFieldValues(commentList, "userId", Long.class);
        //通过评论人id 查询评论人信息
        Map<Long, UserInfo> publishInfo = userInfoAPI.findPublishInfo(userId);
        List<CommentVo> commentVos = new ArrayList<>();
        for (Comment comment : commentList) {
            CommentVo commentVo = new CommentVo();
            UserInfo userInfo = publishInfo.get(comment.getUserId());
            commentVo.setId(comment.getId().toHexString());
            commentVo.setAvatar(userInfo.getLogo());
            commentVo.setNickname(userInfo.getNickName());
            commentVo.setContent(comment.getContent());
            commentVo.setCreateDate(comment.getContent());
            Long likeCount = Convert.toLong(redisTemplate.opsForHash().get(Constants.VIDEOS_INTERACT_KEY + comment.getId(), Constants.VIDEO_LIKE_HASHKEY));
            //缓存中没有去mongodb中找
            if (ObjectUtil.isEmpty(likeCount)) {
                likeCount = commentAPI.selectLikeSize(comment.getId().toHexString());
                //存取到redis中
                redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + comment.getId(), Constants.VIDEO_LIKE_HASHKEY, likeCount.toString());
            }
            commentVo.setLikeCount(Convert.toInt(likeCount));
            Boolean isLike = redisTemplate.opsForHash().hasKey(Constants.VIDEOS_INTERACT_KEY + comment.getId(), Constants.VIDEO_ISLIKE_HASHKEY + UserThreadLocal.getUserId());
            //缓存中没有去redis中找
            if (!isLike) {
                isLike = commentAPI.selectIsLike(comment.getId().toHexString(), UserThreadLocal.getUserId());
                //存入redis中
                if (isLike) {
                    redisTemplate.opsForHash().put(Constants.VIDEO_LIKE_HASHKEY + comment.getId(), Constants.VIDEO_ISLIKE_HASHKEY + UserThreadLocal.getUserId(), "1");
                }
            }
            commentVo.setHasLiked(isLike ? 1 : 0);
            commentVos.add(commentVo);
        }

        return new PageResult(page, pagesize, Convert.toLong(commentVos.size()), commentVos);
    }

    @Override
    public void videoCommentLike(String id) {
        Long likeComment = commentService.likeComment(id);

        //存入redis中
        redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + id, Constants.VIDEO_LIKE_HASHKEY, likeComment.toString());
        redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + id, Constants.VIDEO_ISLIKE_HASHKEY + UserThreadLocal.getUserId(), "1");
    }

    @Override
    public void videoCommentDisLike(String id) {
        Long disLikeVideo = videosAPI.disLikeVideo(id, UserThreadLocal.getUserId());

        redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY + id, Constants.VIDEO_LIKE_HASHKEY, disLikeVideo.toString());
        redisTemplate.opsForHash().delete(Constants.VIDEOS_INTERACT_KEY + id, Constants.VIDEO_ISLIKE_HASHKEY);
    }

    @Override
    public void userFocus(String id) {
        FollowUser user = new FollowUser();
        user.setId(new ObjectId());
        user.setUserId(UserThreadLocal.getUserId());
        user.setFollowUserId(Convert.toLong(id));
        user.setCreated(System.currentTimeMillis());
        videosAPI.userFocus(user);
        //加入到redis中
        redisTemplate.opsForHash().put(Constants.VIDEOS_INTERACT_KEY+id,Constants.VIDEO_FOLLOW_HASHKEY+UserThreadLocal.getUserId(),"1");
    }

    @Override
    public void userUnFocus(String id) {
        videosAPI.userUnFocus(Convert.toLong(id), UserThreadLocal.getUserId());
        redisTemplate.opsForHash().delete(Constants.VIDEOS_INTERACT_KEY+id,Constants.VIDEO_FOLLOW_HASHKEY+UserThreadLocal.getUserId());

    }

    @Override
    public void publishComment(String id, String context) {
        Comment comment = new Comment();
        comment.setId(new ObjectId());
        comment.setPublishId(new ObjectId(id));
        comment.setCommentType(2);
        System.out.println(context);
        comment.setContent(context);
        comment.setUserId(UserThreadLocal.getUserId());
        //根据视频id查询userId
        Video video = videosAPI.selectById(id);
        comment.setPublishUserId(video.getUserId());
        comment.setIsParent(false);
        comment.setParentId(null);
        comment.setCreated(System.currentTimeMillis());


        videosAPI.publishComment(comment);
    }
}
